#include "operationfactory.h"
#include "operation.h"

OperationFactory* OperationFactory::factory = 0;
const QString OperationFactory::ADD = QString("000001");
const QString OperationFactory::SUB = QString("000011");
const QString OperationFactory::AND = QString("001001");
const QString OperationFactory::OR = QString("001010");
const QString OperationFactory::XOR = QString("001011");
const QString OperationFactory::LHI = QString("001100");
const QString OperationFactory::SLL = QString("001101");
const QString OperationFactory::SRL = QString("001110");
const QString OperationFactory::SRA = QString("001111");
const QString OperationFactory::SLT = QString("010000");
const QString OperationFactory::SLE = QString("010010");
const QString OperationFactory::SEQ = QString("010100");
const QString OperationFactory::SNE = QString("010101");
const QString OperationFactory::LW = QString("011100");
const QString OperationFactory::LB = QString("010110");
const QString OperationFactory::SB = QString("010111");
const QString OperationFactory::SW = QString("011101");
const QString OperationFactory::BEQZ = QString("101000");
const QString OperationFactory::BNEZ = QString("101001");
const QString OperationFactory::J = QString("101100");
const QString OperationFactory::JR = QString("101101");
const QString OperationFactory::JAL = QString("101110");
const QString OperationFactory::JALR = QString("101111");
const QString OperationFactory::TRAP = QString("110000");
const QString OperationFactory::XFE = QString("110001");

OperationFactory* OperationFactory::getInstance(Memory* memory, CPU* cpu, QObject *parent)
{
    if(factory == 0)
    {
        factory = new OperationFactory(memory, cpu, parent);
    }
    return factory;
}

OperationFactory::OperationFactory(Memory* _memory, CPU* _cpu, QObject *parent) : QObject(parent)
{
    operations.insert(ADD, new ADDOperation(_cpu, _memory, this));
    operationsI.insert(ADD, new ADDIOperation(_cpu, _memory, this));
    operations.insert(SUB, new SUBOperation(_cpu, _memory, this));
    operationsI.insert(SUB, new SUBIOperation(_cpu, _memory, this));
    operations.insert(AND, new ANDOperation(_cpu, _memory, this));
    operationsI.insert(AND, new ANDIOperation(_cpu, _memory, this));
    operations.insert(OR, new OROperation(_cpu, _memory, this));
    operationsI.insert(OR, new ORIOperation(_cpu, _memory, this));
    operations.insert(XOR, new XOROperation(_cpu, _memory, this));
    operationsI.insert(XOR, new XORIOperation(_cpu, _memory, this));
    operationsI.insert(LHI, new LHIOperation(_cpu, _memory, this));
    operations.insert(SLL, new SLLOperation(_cpu, _memory, this));
    operationsI.insert(SLL, new SLLIOperation(_cpu, _memory, this));
    operations.insert(SRL, new SRLOperation(_cpu, _memory, this));
    operationsI.insert(SRL, new SRLIOperation(_cpu, _memory, this));
    operations.insert(SRA, new SRAOperation(_cpu, _memory, this));
    operationsI.insert(SRA, new SRAIOperation(_cpu, _memory, this));
    operations.insert(SLT, new SLTOperation(_cpu, _memory, this));
    operationsI.insert(SLT, new SLTIOperation(_cpu, _memory, this));
    operations.insert(SLE, new SLEOperation(_cpu, _memory, this));
    operationsI.insert(SLE, new SLEIOperation(_cpu, _memory, this));
    operations.insert(SEQ, new SEQOperation(_cpu, _memory, this));
    operationsI.insert(SEQ, new SEQIOperation(_cpu, _memory, this));
    operations.insert(SNE, new SNEOperation(_cpu, _memory, this));
    operationsI.insert(SNE, new SNEIOperation(_cpu, _memory, this));
    //LW,SW,BEQZ,BNEZ,J,JR,JAL,JALR,TRAP,XFE
    operationsI.insert(LW, new LWOperation(_cpu, _memory, this));
    operationsI.insert(SW, new SWOperation(_cpu, _memory, this));
    operationsI.insert(LB, new LBOperation(_cpu, _memory, this));
    operationsI.insert(SB, new SBOperation(_cpu, _memory, this));
    operationsI.insert(BEQZ, new BEQZOperation(_cpu, _memory, this));
    operationsI.insert(BNEZ, new BNEZOperation(_cpu, _memory, this));
    operationsI.insert(J, new JOperation(_cpu, _memory, this));
    operationsI.insert(JR, new JROperation(_cpu, _memory, this));
    operationsI.insert(JAL, new JALOperation(_cpu, _memory, this));
    operationsI.insert(JALR, new JALROperation(_cpu, _memory, this));
    operationsI.insert(TRAP, new TRAPOperation(_cpu, _memory, this));
    operationsI.insert(XFE, new XFEOperation(_cpu, _memory, this));
}

OperationFactory::~OperationFactory()
{
}

Operation* OperationFactory::getOperation(QString IR)
{
    if(IR.mid(0, 6) == QString("000000"))
    {
        return operations[IR.mid(26, 6)];
    }
    else
    {
        return operationsI[IR.mid(0, 6)];
    }
}
